iT邦幫忙

2024 iThome 鐵人賽

DAY 26
0
Mobile Development

從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始系列 第 26

從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day26

  • 分享至 

  • xImage
  •  

Day26 新增3D物件

除了可以放入3D模型在空間之內,也可以用自動生成的方式,產生3D模型出來。

首先先匯入ARKit:

import ARKit

然後新增一個class,這個class就是用來產生模型的class:

@MainActor class Day4ViewModel: ObservableObject {

    private var contentEntity = Entity()
    
    func setupContentEntity() -> Entity {
        let box = ModelEntity(mesh: .generateBox(width: 0.5, height: 0.5, depth: 0.5))
        box.position = SIMD3(x: 10, y: 0, z: -4)

        contentEntity.addChild(box)
        
        return contentEntity
    }
}

@MainActor是表示這個class的所有方法和屬性都會在主執行緒上執行,因為在SwiftUI上的UI更新必須在主執行緒上執行。

ObservableObject表示當屬性發生變化時,將會自動更新。

Entity是一個基本的容器,可以用來產生AR內容,如模型、光源和其它實體。

let box = ModelEntity(mesh: .generateBox(width: 0.5, height: 0.5, depth: 0.5))
創建了一個3D立方體模型,並且根據寬度、高度和深度來產生出一個立方體出來。

box.position = SIMD3(x: 10, y: 0, z: -4)
設置了立方體的空間位置。SIMD3是一個三維向量,用於宣告立方體在x、y、z軸上的位置。這裡將立方體放置在x軸10單位,y軸0 單位,z軸-4單位的位置地方。

contentEntity.addChild(box) 將創建的立方體作為子實體添加到contentEntity中。

回到ImmersiveView,將剛剛的模型加入到場景當中:

struct ImmersiveView: View {
    
    @StateObject var model = Day4ViewModel()

    var body: some View {
        RealityView { content in
            // Add the initial RealityKit content
            if let scene = try? await Entity(named: "Immersive", in: realityKitContentBundle) {
                content.add(scene)
            }
            
            content.add(model.setupContentEntity())
        }
    }
}

在程式進入點也宣告使用ImmersiveSpace:

import SwiftUI

@main
struct TestVision2App: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
        }
        
        ImmersiveSpace(id: "ImmersiveSpace") {
            ImmersiveView()
        }
    }
}

回到ContentView,稍微修改一下畫面內容:

import SwiftUI
import RealityKit
import RealityKitContent

struct ContentView: View {
    
    @State private var showImmersiveSpace = false
    
    @Environment(\.openImmersiveSpace) var openImmersiveSpace
    @Environment(\.dismissImmersiveSpace) var dismissImmersiveSpace
    
    var body: some View {
        VStack {
            Toggle("Show ImmersiveSpace", isOn: $showImmersiveSpace)
                .font(.title)
                .frame(width: 360)
                .padding(24)
                .glassBackgroundEffect()
        }
        .padding()
        .onChange(of: showImmersiveSpace) { _, newValue in
            Task {
                if newValue {
                    await openImmersiveSpace(id: "ImmersiveSpace")
                }
                else {
                    await dismissImmersiveSpace()
                }
            }
        }
    }
}

這裡只會顯示一個開關,用來開啟沉浸式空間的內容。

如圖顯示:

https://ithelp.ithome.com.tw/upload/images/20240826/2016260700Htaf5cTi.png

開啟開關之後,就會出現一個立方體。

如圖顯示:

https://ithelp.ithome.com.tw/upload/images/20240826/20162607B861WbrVs2.png

生成立方體的完成程式碼:

import SwiftUI
import RealityKit
import RealityKitContent

import ARKit

struct ImmersiveView: View {
    
    @StateObject var model = Day4ViewModel()
    
    var body: some View {
        RealityView { content in
            if let scene = try? await Entity(named: "Immersive", in: realityKitContentBundle) {
                content.add(scene)
            }
            
            content.add(model.setupContentEntity())
        }
    }
}

@MainActor class Day4ViewModel: ObservableObject {
    
    private var contentEntity = Entity()
    
    func setupContentEntity() -> Entity {
        let box = ModelEntity(mesh: .generateBox(width: 0.5, height: 0.5, depth: 0.5))
        box.position = SIMD3(x: 0, y: 2, z: -1)
        
        contentEntity.addChild(box)
        
        return contentEntity
    }
}

從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day26 [完]


上一篇
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day25
下一篇
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始 Day27
系列文
從 SwiftUI 到 Apple Vision Pro - SwiftUI 從零開始30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言